/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "timeline_client.h"
#include "timeline_common.h"

#include <iservice_registry.h>
#include <if_system_ability_manager.h>
#include <ipc_skeleton.h>
#include <system_ability_definition.h>

namespace OHOS {
namespace Msdp {
TimelineClient::TimelineClient() {}
TimelineClient::~TimelineClient()
{
    if (timelineProxy_ != nullptr) {
        auto remoteObject = timelineProxy_->AsObject();
        if (remoteObject != nullptr) {
            remoteObject->RemoveDeathRecipient(deathRecipient_);
        }
    }
}

ErrCode TimelineClient::Connect()
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (timelineProxy_ != nullptr) {
        return ERR_OK;
    }

    sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (sam == nullptr) {
        TIMELINE_HILOGE(TIMELINE_MODULE_INNERKIT, "GetSystemAbilityManager failed");
        return E_TIMELINE_GET_SYSTEM_ABILITY_MANAGER_FAILED;
    }

    sptr<IRemoteObject> remoteObject_ = sam->CheckSystemAbility(MSDP_TIMELINE_SERVICE_ID);
    if (remoteObject_ == nullptr) {
        TIMELINE_HILOGE(TIMELINE_MODULE_INNERKIT, "CheckSystemAbility failed");
        return E_TIMELINE_GET_SERVICE_FAILED;
    }

    deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new TimelineDeathRecipient());
    if (deathRecipient_ == nullptr) {
        TIMELINE_HILOGE(TIMELINE_MODULE_INNERKIT, "Failed to create TimelineDeathRecipient");
        return ERR_NO_MEMORY;
    }

    if ((remoteObject_->IsProxyObject()) && (!remoteObject_->AddDeathRecipient(deathRecipient_))) {
        TIMELINE_HILOGE(TIMELINE_MODULE_INNERKIT, "Add death recipient to Timeline service failed");
        return E_TIMELINE_ADD_DEATH_RECIPIENT_FAILED;
    }

    timelineProxy_ = iface_cast<ITimeline>(remoteObject_);
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Connecting TimelineService success");
    return ERR_OK;

}

void TimelineClient::ResetProxy(const wptr<IRemoteObject>& remote)
{
    std::lock_guard<std::mutex> lock(mutex_);
    TIMELINE_RETURN_IF(timelineProxy_ == nullptr);

    auto serviceRemote = timelineProxy_->AsObject();
    if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
        serviceRemote->RemoveDeathRecipient(deathRecipient_);
        timelineProxy_ = nullptr;
    }
}

void TimelineClient::TimelineDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
{
    if (remote == nullptr) {
        TIMELINE_HILOGE(TIMELINE_MODULE_INNERKIT, "OnRemoteDied failed, remote is nullptr");
        return;
    }

    TimelineClient::GetInstance().ResetProxy(remote);
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Recv death notice");
}

void TimelineClient::Subscribe(const TimelineDataUtils::TimelineArea& area, const sptr<ITimelineCallback>& callback)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Enter");
    TIMELINE_RETURN_IF((callback == nullptr) || (Connect() != ERR_OK));
    timelineProxy_->Subscribe(area, callback);
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Exit");
}

void TimelineClient::UnSubscribe(const TimelineDataUtils::TimelineArea& area, const sptr<ITimelineCallback>& callback){
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Enter");
    TIMELINE_RETURN_IF((callback == nullptr) || (Connect() != ERR_OK));
    timelineProxy_->UnSubscribe(area, callback);
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "Exit");
}

bool TimelineClient::SetPositionState(int32_t homevalue, int32_t companyvalue)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (homevalue > 1 || companyvalue > 1 || homevalue == companyvalue) {
        return 0;
    }
    return timelineProxy_->SetPositionState(homevalue, companyvalue);
}

bool TimelineClient::SetHomePosition(double longitude, double latitude)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (longitude > 180 || longitude < -180 || latitude > 90 || latitude < -90){
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::SetHomePosition : Not Correct Position");
        return 0;
    }
    return timelineProxy_->SetHomePosition(longitude, latitude);
}

bool TimelineClient::SetCompanyPosition(double longitude, double latitude)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (longitude > 180 || longitude < -180 || latitude > 90 || latitude < -90){
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::SetCompanyPosition : Not Correct Position");
        return 0;
    }
    return timelineProxy_->SetCompanyPosition(longitude, latitude);
}

bool TimelineClient::SetSleepTime(int32_t sleeptime, int32_t wakeuptime)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (sleeptime > 23 || wakeuptime >23 || sleeptime < 0 || wakeuptime < 0 || sleeptime == wakeuptime) {
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::SetSleepTime : Not Correct Time");
        return 0;
    }
    return timelineProxy_->SetSleepTime(sleeptime, wakeuptime);
}

bool TimelineClient::SetRestTime(int32_t resttimestart, int32_t resttimeend)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (resttimestart > 23 || resttimeend >23 || resttimestart < 0 || resttimeend < 0 || resttimestart == resttimeend) {
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::SetRestTime : Not Correct Time");
        return 0;
    }
    return timelineProxy_->SetRestTime(resttimestart, resttimeend);
}

bool TimelineClient::SetWorkTime(int32_t worktimestart, int32_t worktimeend)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    if (worktimestart > 23 || worktimeend >23 || worktimestart < 0 || worktimeend < 0 || worktimestart == worktimeend) {
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::UpdateRestTime : Not Correct Time");
        return 0;
    }
    return timelineProxy_->SetWorkTime(worktimestart, worktimeend);
}

uint32_t TimelineClient::GetSleepTime()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetSleepTime();
}

uint32_t TimelineClient::GetWakeupTime()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetWakeupTime();
}

uint32_t TimelineClient::GetRestTimeStart()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetRestTimeStart();
}

uint32_t TimelineClient::GetRestTimeEnd()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetRestTimeEnd();
}

uint32_t TimelineClient::GetWorkTimeStart()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetWorkTimeStart();
}

uint32_t TimelineClient::GetWorkTimeEnd()
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);\
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, 0);
    return timelineProxy_->GetWorkTimeEnd();
}

// bool TimelineClient::SetForcecast(uint32_t time)
// {
//     TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
//     return timelineProxy_->SetForcecast(uint32_t time);
// }
TimelineDatabaseInfo::ForcecastPosition TimelineClient::GetForcecast(uint32_t time)
{
    TIMELINE_HILOGD(TIMELINE_MODULE_INNERKIT, "%{public}s Enter!", __func__);
    TIMELINE_RETURN_IF_WITH_RET(Connect() != ERR_OK, TimelineDatabaseInfo::ForcecastPosition::UNKNOWN);
    if (time > 23 || time < 0){
        TIMELINE_HILOGE(TIMELINE_MODULE_SERVICE, "TimelineService::GetForcecast : Not Correct Time");
        return TimelineDatabaseInfo::ForcecastPosition::UNKNOWN;
    }
    return timelineProxy_->GetForcecast(time);
}
} // namespace Msdp
} // namespace OHOS